﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using YJKArchMethodLibrary.Utils;

namespace DormantWindow
{
	public class DrawingPlotter
	{
        public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<CurveInfo> curves, List<TextNoteInfo> textNotes, List<FillRegion> fillRegions)
		{
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_Curves = curves;
			this.m_TextNotes = textNotes;
			this.m_FillRegions = fillRegions;
		}

		public void Draw(bool transparent)
		{
			if (this.m_Curves.Count < 1 && this.m_TextNotes.Count == 0 && this.m_FillRegions.Count == 0)
			{
				return;
			}
			this.m_Graphics.SmoothingMode = SmoothingMode.HighQuality;
			this.m_Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
            this.m_Graphics.Clear(System.Drawing.Color.White);
			Size size = this.m_Control.Size;
			Size size2 = new Size(Common.Rounding((double)size.Width), Common.Rounding((double)size.Height));
			Transform trans = this.ComputerTransMatrix(size2);
			List<CurveInfo> list = new List<CurveInfo>();
			list.AddRange(this.m_Curves);
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				this.DrawFillRegion(fillRegion, trans, transparent);
			}
			foreach (CurveInfo curveInfo in list)
			{
				Pen penWithCurveInfo = this.GetPenWithCurveInfo(curveInfo.Color, curveInfo.PenDashStyle, curveInfo.LineWidth);
				EdgeInfo curveObj = curveInfo.CurveObj;
				if (Geometry.IsEqual(curveObj.Bulge, 0.0))
				{
					this.DrawLine(penWithCurveInfo, curveObj.StartPoint, curveObj.EndPoint, trans);
				}
				else
				{
					this.DrawArc(penWithCurveInfo, curveObj.StartPoint, curveObj.EndPoint, curveObj.Bulge, trans);
				}
			}
			foreach (TextNoteInfo textNoteInfo in this.m_TextNotes)
			{
				this.DrawText(textNoteInfo, trans);
			}
		}

		public void GetTransform(ref Transform trans)
		{
			if (this.m_Curves.Count < 1)
			{
				trans = Transform.Identity;
				return;
			}
			Size size = this.m_Control.Size;
			Size size2 = new Size(Common.Rounding((double)size.Width), Common.Rounding((double)size.Height));
			trans = this.ComputerTransMatrix(size2);
		}

		private Pen GetPenWithCurveInfo(PenColor penColor, DashStyle penDashStyle, float lineWidth)
		{
            System.Drawing.Color color = this.PenColorToColor(penColor);
			return new Pen(color, lineWidth)
			{
				DashStyle = penDashStyle
			};
		}

        private System.Drawing.Color PenColorToColor(PenColor penColor)
		{
            System.Drawing.Color white = System.Drawing.Color.White;
			switch (penColor)
			{
			case PenColor.PC_Red:
            return System.Drawing.Color.Red;
			case PenColor.PC_Blue:
            return System.Drawing.Color.Blue;
			case PenColor.PC_Green:
            return System.Drawing.Color.Green;
			case PenColor.PC_Gray:
            return System.Drawing.Color.Gray;
			case PenColor.PC_Yellow:
                return System.Drawing.Color.Yellow;
			case PenColor.PC_Black:
                return System.Drawing.Color.Black;
			case PenColor.PC_LightBlue:
                return System.Drawing.Color.LightBlue;
			case PenColor.PC_LightGray:
                return System.Drawing.Color.LightGray;
			}
            return System.Drawing.Color.White;
		}

		private Transform ComputerTransMatrix(Size size)
		{
			Transform identity = Transform.Identity;
			identity.Origin = XYZ.Zero;
			identity.BasisX = XYZ.BasisX;
			identity.BasisY = -XYZ.BasisY;
			identity.BasisZ = XYZ.BasisZ;
			BoundingBoxUV boundingBox = this.GetBoundingBox();
			UV max = boundingBox.Max;
			UV min = boundingBox.Min;
			double num = (double)size.Width / (max.U - min.U);
			double num2 = (double)size.Height / (max.V - min.V);
			double num3 = (num <= num2) ? num : num2;
			if (double.IsInfinity(num3))
			{
				num3 = 1.0;
			}
			Transform transform = Transform.Identity;
			transform = transform.ScaleBasis(num3 * 0.95);
			XYZ vector = new XYZ((min.U + max.U) / 2.0, (min.V + max.V) / 2.0, 0.0);
			Transform transform2 = RevitVersionFuncs.CreateTranslation(vector);
			Transform transform3 = Transform.Identity;
			transform3 = transform3.Multiply(identity.Inverse);
			transform3 = transform3.Multiply(transform);
			return transform3.Multiply(transform2.Inverse);
		}

		public BoundingBoxUV GetBoundingBox()
		{
			BoundingBoxUV boundingBoxUV = null;
			List<EdgeInfo> list = new List<EdgeInfo>();
			foreach (CurveInfo curveInfo in this.m_Curves)
			{
				EdgeInfo curveObj = curveInfo.CurveObj;
				list.Add(curveObj);
			}
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				list.AddRange(fillRegion.EdgeLoop);
			}
			foreach (EdgeInfo edgeInfo in list)
			{
				if (Geometry.IsEqual(edgeInfo.Bulge, 0.0))
				{
					if (boundingBoxUV == null)
					{
						boundingBoxUV = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
					}
					else
					{
						BoundingBoxUV box = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
						boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box);
					}
				}
				else
				{
					XYZ startPoint = edgeInfo.StartPoint;
					XYZ endPoint = edgeInfo.EndPoint;
					XYZ ptCenter = null;
					XYZ normal = XYZ.BasisZ;
					double radius = 0.0;
					double num = 0.0;
					double num2 = 0.0;
					Geometry.GetArcInfoWithBulge(startPoint, endPoint, edgeInfo.Bulge, ref ptCenter, ref radius, ref num, ref num2);
					if (Geometry.LessThan(edgeInfo.Bulge, 0.0))
					{
						normal = -XYZ.BasisZ;
					}
					if (boundingBoxUV == null)
					{
						boundingBoxUV = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
					}
					else
					{
						BoundingBoxUV box2 = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
						boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box2);
					}
				}
			}
			return boundingBoxUV;
		}

		private void DrawLine(Pen pen, XYZ ptS, XYZ ptE, Transform trans)
		{
			ptS = Geometry.TransformPoint(ptS, trans);
			ptE = Geometry.TransformPoint(ptE, trans);
			PointF pt = new PointF((float)ptS.X, (float)ptS.Y);
			PointF pt2 = new PointF((float)ptE.X, (float)ptE.Y);
			this.m_Graphics.DrawLine(pen, pt, pt2);
		}

		private void DrawArc(Pen pen, XYZ ptS, XYZ ptE, double bugle, Transform trans)
		{
			XYZ xyz = null;
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			Geometry.GetArcInfoWithBulge(ptS, ptE, bugle, ref xyz, ref num, ref num2, ref num3);
			float num4 = (float)(num * trans.Scale);
			XYZ basisZ = XYZ.BasisZ;
			if (Geometry.LessThan(bugle, 0.0))
			{
                //-XYZ.BasisZ;
			}
			float num5 = 6.28318548f - (float)num3;
			float num6 = 6.28318548f - (float)num2;
			if (num5 > num6)
			{
				num6 += 6.28318548f;
			}
			float num7 = num6 - num5;
			num5 = num5 * 180f / 3.14159274f;
			num7 = num7 * 180f / 3.14159274f;
			xyz = Geometry.TransformPoint(xyz, trans);
			float x = (float)(xyz.X - (double)num4);
			float y = (float)(xyz.Y - (double)num4);
			float num8 = num4 * 2f;
			this.m_Graphics.DrawArc(pen, x, y, num8, num8, num5, num7);
		}

		private void DrawText(TextNoteInfo textNoteInfo, Transform trans)
		{
			if (textNoteInfo.m_Text.CompareTo("") == 0)
			{
				return;
			}
			float emSize = (float)(textNoteInfo.m_Height * trans.Scale);
			Font font = new Font("宋体", emSize);
            System.Drawing.Color color = this.PenColorToColor(textNoteInfo.m_Color);
			SolidBrush brush = new SolidBrush(color);
			XYZ xyz = Geometry.TransformPoint(textNoteInfo.m_Center, trans);
			double num = textNoteInfo.m_BoundingBoxWidth * trans.Scale;
			double num2 = textNoteInfo.m_BoundingBoxHeight * trans.Scale;
			double num3 = xyz.X - num / 2.0;
			double num4 = xyz.Y - num2 / 2.0;
			Rectangle r = new Rectangle((int)num3, (int)num4, (int)num, (int)num2);
			StringFormat stringFormat = new StringFormat();
			stringFormat.LineAlignment = StringAlignment.Center;
			stringFormat.Alignment = StringAlignment.Center;
			this.m_Graphics.DrawString(textNoteInfo.m_Text, font, brush, r, stringFormat);
		}

		private void DrawFillRegion(FillRegion fillRegion, Transform trans, bool transparent)
		{
			try
			{
				List<EdgeInfo> edgeLoop = fillRegion.EdgeLoop;
				List<XYZ> list = new List<XYZ>();
				List<double> list2 = new List<double>();
				double num = 0.0;
				for (int i = 0; i < edgeLoop.Count; i++)
				{
					EdgeInfo edgeInfo = edgeLoop[i];
					num += edgeInfo.Length();
					list.Add(edgeInfo.StartPoint);
					list2.Add(edgeInfo.Bulge);
				}
				double fitSpace = num / (double)edgeLoop.Count / 10.0;
				List<XYZ> list3 = new List<XYZ>();
				Geometry.GetFittingPolyline(list, list2, ref list3, fitSpace);
				for (int i = 0; i < list3.Count; i++)
				{
					list3[i] = Geometry.TransformPoint(list3[i], trans);
				}
				GraphicsPath graphicsPath = new GraphicsPath();
				for (int i = 0; i < list3.Count; i++)
				{
					XYZ xyz = list3[i];
					XYZ xyz2;
					if (i == list3.Count - 1)
					{
						xyz2 = list3[0];
					}
					else
					{
						xyz2 = list3[i + 1];
					}
					graphicsPath.AddLine((float)xyz.X, (float)xyz.Y, (float)xyz2.X, (float)xyz2.Y);
				}
				XYZ xyz3 = new XYZ(-1.0, -1.0, 1.0);
				double num2 = Math.Abs(xyz3.AngleTo(fillRegion.Normal()));
				if (Geometry.GreaterThan(num2, Math.PI*.5))
				{
					num2 = Math.PI - num2;
				}
				double num3 = 1.0 - num2 / Math.PI;
                System.Drawing.Color color = this.PenColorToColor(fillRegion.Color);
				int num4 = (int)color.A;
				if (transparent)
				{
					num4 = (int)((double)num4 * 0.5);
				}
				int red = (int)((double)color.R * num3);
				int green = (int)((double)color.G * num3);
				int blue = (int)((double)color.B * num3);
                System.Drawing.Color color2 = System.Drawing.Color.FromArgb(num4, red, green, blue);
				Brush brush = new SolidBrush(color2);
				this.m_Graphics.FillRegion(brush, new Region(graphicsPath));
                Pen pen = new Pen(System.Drawing.Color.Gray, 1f);
				for (int i = 0; i < list3.Count; i++)
				{
					if (!fillRegion.EdgeIsTransparent[i])
					{
						XYZ ptS = list3[i];
						XYZ ptE;
						if (i == list3.Count - 1)
						{
							ptE = list3[0];
						}
						else
						{
							ptE = list3[i + 1];
						}
						this.DrawLine(pen, ptS, ptE, Transform.Identity);
					}
				}
			}
			catch (Exception)
			{
			}
		}

		private List<CurveInfo> m_Curves = new List<CurveInfo>();

		private List<TextNoteInfo> m_TextNotes = new List<TextNoteInfo>();

		private List<FillRegion> m_FillRegions = new List<FillRegion>();

		private Graphics m_Graphics;

        private System.Windows.Forms.Control m_Control;
	}
}
